home *** CD-ROM | disk | FTP | other *** search
/ Cream of the Crop 22 / Cream of the Crop 22.iso / os2 / ext2_200.zip / EXT2_SRC.ZIP / 32BITS / EXT2-OS2 / EXT2FLT / E2PART.C < prev    next >
C/C++ Source or Header  |  1996-01-24  |  11KB  |  290 lines

  1. /************************************************************************/
  2. /*                       Linux partition filter.                        */
  3. /*          (C) Copyright Deon van der Westhuysen, July 1995.           */
  4. /*                                                                      */
  5. /*  Dedicated to Jesus Christ, my Lord and Saviour.                     */
  6. /*                                                                      */
  7. /* This program is free software; you can redistribute it and/or modify */
  8. /* it under the terms of the GNU General Public License as published by */
  9. /* the Free Software Foundation; either version 2, or (at your option)  */
  10. /* any later version.                                                   */
  11. /*                                                                      */
  12. /* This program is distributed in the hope that it will be useful,      */
  13. /* but WITHOUT ANY WARRANTY; without even the implied warranty of       */
  14. /* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the        */
  15. /* GNU General Public License for more details.                         */
  16. /*                                                                      */
  17. /* You should have received a copy of the GNU General Public License    */
  18. /* along with this program; if not, write to the Free Software          */
  19. /* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.            */
  20. /*                                                                      */
  21. /*  This code is still under development; expect some rough edges.      */
  22. /*                                                                      */
  23. /************************************************************************/
  24.  
  25. #include "debug.h"
  26. #include "e2data.h"
  27. #include "e2router.h"
  28. #include "e2part.h"
  29. #include "e2iocmd.h"
  30. #include "e2virtio.h"
  31. #include "e2wrap.h"
  32.  
  33. /* All IORBs for the virtual units (containing the virtual partitions) */
  34. /* arrive here. From here it is routed to the function to service the */
  35. /* command. */
  36. void PartHandler (PIORB pIORB)
  37. {
  38.  NPVirtUnitRec    pUnitRec;            /* Pointer to unit record */
  39.  USHORT        Command;            /* Command to executed */
  40.  USHORT        Modifier;            /* Modifier for the command */
  41.  
  42.  Command= pIORB->CommandCode;            /* Get command to execute */
  43.  Modifier= pIORB->CommandModifier;        /* Get modifier for command */
  44.  if (Command==IOCC_CONFIGURATION)
  45.   pUnitRec= VirtUnits;                /* Default unit for the */
  46.                         /* configuration request */
  47.  else
  48.   pUnitRec= (NPVirtUnitRec) pIORB->UnitHandle;    /* Get unit record for IORB */
  49.  
  50.  /* Route request to appropiate service routine. */
  51.  switch (Command)
  52.  {
  53.   case IOCC_CONFIGURATION:
  54.         switch (Modifier)
  55.         {
  56.          case IOCM_GET_DEVICE_TABLE:
  57.                 PartGetDeviceTable (pUnitRec,pIORB);
  58.                 break;
  59.          default:    BadCommand (pUnitRec,pIORB);
  60.                 break;
  61.         }
  62.         break;
  63.   case IOCC_UNIT_CONTROL:
  64.         switch (Modifier)
  65.         {
  66.          case IOCM_CHANGE_UNITINFO:
  67.                 PartChangeUnitInfo (pUnitRec,pIORB);
  68.                 break;
  69.          default:    BadCommand (pUnitRec,pIORB);
  70.                 break;
  71.         }
  72.         break;
  73.   case IOCC_GEOMETRY:
  74.         switch (Modifier)
  75.         {
  76.          case IOCM_GET_MEDIA_GEOMETRY:
  77.          case IOCM_GET_DEVICE_GEOMETRY:
  78.                 PartGetGeometry (pUnitRec,pIORB);
  79.                 break;
  80.          default:    BadCommand (pUnitRec,pIORB);
  81.                 break;
  82.         }
  83.         break;
  84.   case IOCC_EXECUTE_IO:
  85.         switch (Modifier)
  86.         {
  87.          case IOCM_READ:
  88.          case IOCM_READ_VERIFY:
  89.          case IOCM_WRITE:
  90.          case IOCM_WRITE_VERIFY:
  91.                 PartDoIO (pUnitRec,pIORB);
  92.                 break;
  93.          default:    BadCommand (pUnitRec,pIORB);
  94.                 break;
  95.         }
  96.         break;
  97.   case IOCC_UNIT_STATUS:
  98.         switch (Modifier)
  99.         {
  100.          case IOCM_GET_UNIT_STATUS:
  101.                 PartGetUnitStatus (pUnitRec,pIORB);
  102.                 break;
  103.          default:    BadCommand (pUnitRec,pIORB);
  104.                 break;
  105.         }
  106.         break;
  107.   defualt:    BadCommand (pUnitRec,pIORB);
  108.         break;
  109.  }
  110. }
  111.  
  112. /* This function is called by the original device driver after the IORB */
  113. /* request is satisfied. We restore the IORB before we pass it back to the */
  114. /* caller. */
  115. void PartNotify (PIORB pIORB)
  116. {
  117. #define pIOXIO        ((PIORB_EXECUTEIO) pIORB)
  118.  
  119.  NPVirtUnitRec    pUnitRec;            /* Ptr to unit record */
  120.  ULONG        PatchOffset;            /* Used to fix up boot sec */
  121.  ULONG        PatchValue;
  122.  
  123.  if (pIORB->CommandCode==IOCC_CONFIGURATION)    /* If configuration IORB */
  124.   pUnitRec= VirtUnits;                /* Default unit for the */
  125.                         /* configuration request */
  126.  else
  127.   pUnitRec= (NPVirtUnitRec) pIORB->Reserved_1;    /* Get unit record from IORB */
  128.  
  129.  /* Reverse any mappings that may have been done... */
  130.  pIORB->UnitHandle= pIORB->Reserved_1;        /* Restore IORB fields */
  131.  pIORB->RequestControl= pUnitRec->SaveReqCtrl; 
  132.  pIORB->Reserved_1= pUnitRec->SaveReserved;
  133.  pIORB->NotifyAddress= pUnitRec->SaveNotify;
  134.  if (pIORB->CommandCode==IOCC_EXECUTE_IO)    /* If request involded IO */
  135.  {
  136.   /* Restore RBA and BlockCount fields, modify BlocksXferred... */
  137.   pIOXIO->RBA= pUnitRec->SaveRBA;        
  138.   pIOXIO->BlockCount= pUnitRec->SaveBlockCount;
  139.   pIOXIO->BlocksXferred+= pUnitRec->SectorsDone;
  140.  
  141.   /* If the scatter/gather list was modified then restore it as well. */
  142.   if ((pUnitRec->SGOffset)&&(pIORB->CommandModifier!=IOCM_READ_VERIFY))
  143.   {
  144.    /* If we didn't run out of SG list elements... */
  145.    if (pIOXIO->cSGList)
  146.     memcpy (pIOXIO->pSGList,&(pUnitRec->SaveSGEntry),sizeof(SCATGATENTRY));
  147.    pIOXIO->cSGList= pUnitRec->SavecSGList;
  148.    pIOXIO->pSGList= pUnitRec->SavepSGList;
  149.    pIOXIO->ppSGList= pUnitRec->SaveppSGList;
  150.   }
  151.  
  152.   /* OK first 'patch' here: if the FS type is FAT and the bootsector was */
  153.   /* read them we must change the 'Hidden Sectors' field. */
  154.   if ((pIOXIO->RBA<=pUnitRec->NumExtraSectors)&&
  155.       ((pIOXIO->RBA+pIOXIO->BlockCount)>pUnitRec->NumExtraSectors))
  156.   {
  157.    PatchOffset= 0x1C+(pUnitRec->NumExtraSectors-pIOXIO->RBA)*SECTOR_SIZE;
  158.    if ((pIORB->CommandModifier==IOCM_READ)||
  159.        (pIORB->CommandModifier==IOCM_WRITE)||
  160.        (pIORB->CommandModifier==IOCM_WRITE_VERIFY))  
  161.    {
  162.     PatchValue= pUnitRec->NumExtraSectors-
  163.                 (pUnitRec->pSourceUnitRec->GeoNumHeads*
  164.                  pUnitRec->pSourceUnitRec->GeoTrackSec); 
  165.     CopyToSGList (&PatchValue,sizeof(PatchValue),
  166.                   pIOXIO->pSGList,pIOXIO->cSGList,PatchOffset);
  167.    }
  168.   }
  169.  }
  170.  /* Notify the caller and restart the queue. */
  171.  PartCommandDone (pUnitRec,pIORB);
  172.  
  173. #undef pIOXIO
  174. }
  175.  
  176. /* Pass the IORB to the base unit containing the source data for the virtual */
  177. /* unit. Remap IO addresses to map virtual partition unto base data. */
  178. void PartFilterIORB (NPVirtUnitRec pUnitRec, PIORB pIORB)
  179. {
  180. #define pIOXIO        ((PIORB_EXECUTEIO) pIORB)
  181.  
  182.  USHORT        SectorsDone;            /* Num virtual sectors */
  183.                         /* allready serviced */
  184.  ULONG        XferOffset;            /* Offset in SG to start IO */
  185.  ULONG        PatchOffset;            /* Used to fix up boot sec */
  186.  
  187.  pUnitRec->SaveReqCtrl= pIORB->RequestControl;    /* Save request control */
  188.  pUnitRec->SaveReserved= pIORB->Reserved_1;    /* Save reserved field */
  189.  pUnitRec->SaveNotify= pIORB->NotifyAddress;    /* Save old notify address */
  190.  pIORB->Reserved_1= pIORB->UnitHandle;        /* Save our old handle */
  191.  
  192.  pIORB->RequestControl|= IORB_ASYNC_POST;    /* Ask for notification */
  193.  pIORB->RequestControl&= ~IORB_CHAIN;        /* Disable chained request */
  194.  pIORB->NotifyAddress= &PartNotifyWrapper;    /* Set our notify address */
  195.  pIORB->UnitHandle= (USHORT) pUnitRec->pSourceUnitRec;
  196.                         /* Handle for our filter */
  197.  
  198.  /* Patch up IORB further for IO requests. */
  199.  if (pIORB->CommandCode==IOCC_EXECUTE_IO)    /* If IO command... */
  200.  {
  201.   /* Patch hidden sector count */
  202.   if ((pIOXIO->RBA<=pUnitRec->NumExtraSectors)&&
  203.       ((pIOXIO->RBA+pIOXIO->BlockCount)>pUnitRec->NumExtraSectors))
  204.   {
  205.    PatchOffset= 0x1C+(pUnitRec->NumExtraSectors-pIOXIO->RBA)*SECTOR_SIZE;
  206.    if ((pIORB->CommandModifier==IOCM_WRITE)||
  207.        (pIORB->CommandModifier==IOCM_WRITE_VERIFY))  
  208.    {
  209.     CopyToSGList (&pUnitRec->HiddenSectors,sizeof(ULONG),
  210.                   pIOXIO->pSGList,pIOXIO->cSGList,PatchOffset);
  211.    }
  212.   }
  213.  
  214.   pUnitRec->SaveBlockCount= pIOXIO->BlockCount;    /* Save IORB IO fields */
  215.   pUnitRec->SectorsDone= pIOXIO->BlocksXferred;
  216.   pUnitRec->SaveRBA= pIOXIO->RBA;
  217.  
  218.   pIOXIO->BlockCount-= pIOXIO->BlocksXferred;    /* Subtract num blocks we */
  219.                         /* allready transfered
  220.   pIOXIO->BlocksXferred= 0;            /* Reset transfer count */
  221.  
  222.   /* Calculate the start sector for the request... */
  223.   if (pIOXIO->RBA<pUnitRec->NumVirtualSectors)        
  224.   {                        /* Includes virtual sectors */
  225.    XferOffset= (pUnitRec->NumVirtualSectors-pIOXIO->RBA)*SECTOR_SIZE;
  226.                         /* Calculate number of bytes */
  227.                         /* to skip past virt sectors */ 
  228.    pIOXIO->RBA= pUnitRec->NumVirtualSectors-pUnitRec->NumExtraSectors+
  229.                 pUnitRec->StartRBA;        /* Calc starting RBA address */
  230.   }
  231.   else
  232.   {                        /* Past virtual sectors */
  233.    XferOffset= 0;                /* No need to skip bytes */
  234.    pIOXIO->RBA= pIOXIO->RBA-pUnitRec->NumExtraSectors+pUnitRec->StartRBA;
  235.                         /* Calc starting RBA address */
  236.   }
  237.   pUnitRec->SGOffset= XferOffset;        /* Save transfer offset */
  238.  
  239.   /* CHECK WAYS OF CHOPPING BLOCK COUNT */
  240.   /* Safety net: chop block count if neccessary: */
  241.   if ((pIOXIO->RBA+pIOXIO->BlockCount)>        /* If past source data */
  242.       (pUnitRec->StartRBA+pUnitRec->NumSectors))    
  243.   {
  244.    BREAK
  245.    pIOXIO->BlockCount= 0;            /* Tough: kill request... */
  246.   }
  247.  
  248.   /* Also modify scatgat list if neccessary... */
  249.   if ((XferOffset)&&(pIORB->CommandModifier!=IOCM_READ_VERIFY))
  250.   {
  251.    /* First save original pointers... */
  252.    pUnitRec->SavecSGList= pIOXIO->cSGList;
  253.    pUnitRec->SavepSGList= pIOXIO->pSGList;
  254.    pUnitRec->SaveppSGList= pIOXIO->ppSGList;
  255.  
  256.    /* Seek to the offset to start IO */
  257.    while ((pIOXIO->cSGList)&&(pIOXIO->pSGList->XferBufLen<=XferOffset))
  258.    {                        /* Skip past SG entries */
  259.     XferOffset-=(pIOXIO->pSGList++)->XferBufLen;
  260.     pIOXIO->cSGList--;
  261.     pIOXIO->ppSGList+= sizeof (SCATGATENTRY);
  262.    }
  263.  
  264.    /* If we didn't run out of SG list elements... */
  265.    if (pIOXIO->cSGList)
  266.    {
  267.     memcpy (&(pUnitRec->SaveSGEntry),pIOXIO->pSGList,sizeof(SCATGATENTRY));
  268.     pIOXIO->pSGList->XferBufLen-= XferOffset;
  269.     pIOXIO->pSGList->ppXferBuf+= XferOffset;
  270.    }
  271.   }
  272.  }
  273.  E2FilterIORB (pIORB);        /* Ask our handler to handle it further... */
  274.  
  275. #undef pIOXIO
  276. }
  277.  
  278. /* Function that is called when the routine that services the IORB has */
  279. /* finished processing that IORB. We notify the caller and try to restart */
  280. /* the IORB queue. */
  281. void PartCommandDone (NPVirtUnitRec pUnitRec, PIORB pIORB)
  282. {
  283.  NPIORBQueue    pQueue;                /* Pointer to IORB queue */
  284.  
  285.  pQueue= &(pUnitRec->Hdr.IORBQueue);        /* Get pointer to queue */
  286.  pQueue->Flags&=~F_REQUEST_BUSY;        /* Indicate queue finished */
  287.  NotifyDone (pIORB);                /* Notify caller */
  288.  StartIORBQueue (pQueue);            /* Try to restart queue */
  289. }
  290.